package com.zkteco.fingerprint.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zkteco.fingerprint.service.FingerprintDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 指纹识别WebSocket处理器
 * 处理前端与后端的实时通信
 */
@Component
public class FingerprintWebSocketHandler implements WebSocketHandler {
    
    @Autowired
    private FingerprintDeviceService deviceService;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
    
    // ==================== WebSocket生命周期方法 ====================
    
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);
        setupDeviceCallbacks(session);
        sendMessage(session, "connection", "WebSocket连接成功");
    }
    
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String payload = message.getPayload().toString();
        
        try {
            Map<String, Object> data = parseMessage(payload);
            String action = (String) data.get("action");
            
            if (action == null) {
                sendError(session, "操作类型不能为空");
                return;
            }
            
            processAction(session, action, data);
            
        } catch (Exception e) {
            sendError(session, "消息处理错误: " + e.getMessage());
        }
    }
    
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        sendError(session, "传输错误: " + exception.getMessage());
    }
    
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        sessions.remove(session.getId());
        deviceService.stopCurrentOperation();
    }
    
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    
    // ==================== 初始化和回调设置 ====================
    
    /**
     * 设置设备服务回调
     */
    private void setupDeviceCallbacks(WebSocketSession session) {
        deviceService.setMessageCallback(message -> {
            sendMessage(session, "message", message);
        });
        
        deviceService.setImageCallback(imageData -> {
            String base64Image = Base64.getEncoder().encodeToString(imageData);
            sendMessage(session, "image", base64Image);
        });
        
        deviceService.setTemplateCallback(template -> {
            sendMessage(session, "template", template);
        });
    }
    
    // ==================== 消息解析和分发 ====================
    
    /**
     * 解析前端消息
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> parseMessage(String payload) throws Exception {
        return objectMapper.readValue(payload, Map.class);
    }
    
    /**
     * 处理具体操作
     */
    private void processAction(WebSocketSession session, String action, Map<String, Object> data) {
        switch (action) {
            case "connect":
                handleConnect(session);
                break;
            case "disconnect":
                handleDisconnect(session);
                break;
            case "enroll":
                handleEnroll(session, data);
                break;
            case "verify":
                handleVerify(session, data);
                break;
            case "stop":
                handleStop(session);
                break;
            default:
                sendError(session, "未知操作: " + action);
        }
    }
    
    // ==================== 操作处理方法 ====================
    
    /**
     * 处理设备连接
     */
    private void handleConnect(WebSocketSession session) {
        boolean success = deviceService.connectDevice();
        sendMessage(session, "connect_result", success ? "连接成功" : "连接失败");
        sendMessage(session, "device_status", deviceService.isDeviceConnected());
    }
    
    /**
     * 处理设备断开
     */
    private void handleDisconnect(WebSocketSession session) {
        deviceService.disconnectDevice();
        sendMessage(session, "disconnect_result", "设备已断开");
        sendMessage(session, "device_status", false);
    }
    
    /**
     * 处理指纹录入
     */
    private void handleEnroll(WebSocketSession session, Map<String, Object> data) {
        String userId = (String) data.get("userId");
        String userName = (String) data.get("userName");
        
        if (!validateEnrollParams(session, userId, userName)) {
            return;
        }
        
        deviceService.startEnrollment(userId, userName)
            .thenAccept(template -> handleEnrollResult(session, userId, userName, template))
            .exceptionally(throwable -> {
                sendError(session, "录入异常: " + throwable.getMessage());
                return null;
            });
    }
    
    /**
     * 处理连续指纹验证
     */
    private void handleVerify(WebSocketSession session, Map<String, Object> data) {
        String template = (String) data.get("template");
        
        if (!validateVerifyParams(session, template)) {
            return;
        }
        
        deviceService.startContinuousVerification(template)
            .thenAccept(result -> sendMessage(session, "verify_result", result))
            .exceptionally(throwable -> {
                sendError(session, "验证异常: " + throwable.getMessage());
                return null;
            });
    }
    
    /**
     * 处理停止操作
     */
    private void handleStop(WebSocketSession session) {
        deviceService.stopCurrentOperation();
        sendMessage(session, "operation_stopped", "操作已停止");
    }
    
    // ==================== 参数验证方法 ====================
    
    /**
     * 验证录入参数
     */
    private boolean validateEnrollParams(WebSocketSession session, String userId, String userName) {
        if (userId == null || userId.trim().isEmpty()) {
            sendError(session, "用户ID不能为空");
            return false;
        }
        
        if (userName == null || userName.trim().isEmpty()) {
            sendError(session, "用户姓名不能为空");
            return false;
        }
        
        return true;
    }
    
    /**
     * 验证验证参数
     */
    private boolean validateVerifyParams(WebSocketSession session, String template) {
        if (template == null || template.trim().isEmpty()) {
            sendError(session, "验证模板不能为空");
            return false;
        }
        
        return true;
    }
    
    // ==================== 结果处理方法 ====================
    
    /**
     * 处理录入结果
     */
    private void handleEnrollResult(WebSocketSession session, String userId, String userName, String template) {
        if (template != null) {
            Map<String, Object> result = createEnrollSuccessResult(userId, userName, template);
            sendMessage(session, "enroll_success", result);
        } else {
            sendMessage(session, "enroll_failed", "录入失败");
        }
    }
    
    /**
     * 创建录入成功结果
     */
    private Map<String, Object> createEnrollSuccessResult(String userId, String userName, String template) {
        Map<String, Object> result = new HashMap<>();
        result.put("userId", userId);
        result.put("userName", userName);
        result.put("template", template);
        return result;
    }
    
    // ==================== 消息发送方法 ====================
    
    /**
     * 发送普通消息到前端
     */
    private void sendMessage(WebSocketSession session, String type, Object data) {
        try {
            if (session != null && session.isOpen()) {
                Map<String, Object> message = createMessage(type, data);
                String json = objectMapper.writeValueAsString(message);
                session.sendMessage(new TextMessage(json));
            }
        } catch (IOException e) {
            System.err.println("[WebSocket] 发送消息失败: " + e.getMessage());
        }
    }
    
    /**
     * 发送错误消息到前端
     */
    private void sendError(WebSocketSession session, String errorMessage) {
        sendMessage(session, "error", errorMessage);
    }
    
    /**
     * 创建消息对象
     */
    private Map<String, Object> createMessage(String type, Object data) {
        Map<String, Object> message = new HashMap<>();
        message.put("type", type);
        message.put("data", data);
        message.put("timestamp", System.currentTimeMillis());
        return message;
    }
    
    // ==================== 工具方法 ====================
    
    /**
     * 获取活跃连接数
     */
    public int getActiveSessionCount() {
        return sessions.size();
    }
    
    /**
     * 广播消息到所有连接
     */
    public void broadcastMessage(String type, Object data) {
        sessions.values().forEach(session -> sendMessage(session, type, data));
    }
} 